/*
 * ColaMensajes.cpp
 *
 *  Created on: 02/04/2014
 *      Author: migue
 */

#include "ColaMensajes.h"
#include "../defines.h"
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <string.h>
#include <unistd.h>

#include <errno.h>
#include <stdlib.h>

#include <stdio.h>
#include <iostream>
#include <syslog.h>


void mostrarMensajeCompleto(MENSAJE *msj) {
	//std::cout << *msj << std::endl;
	printf("Info de MENSAJE; destino: %li, destFinal: %li, origen: %li \n", msj->destinatario, msj->destinatarioFinal, msj->origen);
}


ColaMensajes::ColaMensajes(const char* ruta, char id, bool crear) {

	key_t clave = ftok(ruta, id);

	if (clave == -1) {
		syslog(LOG_INFO,
				"Error al obtener clave [ftok(...)], ruta: %s, id: %c, crear: %i",
				ruta, id, crear);
		perror("Error al obtener clave [ftok(...)]");
		exit(EXIT_FAILURE);
	}

	if (crear) {
		_numCola = msgget(clave, IPC_CREAT | IPC_EXCL | 0660);
	} else {
		_numCola = msgget(clave, 0660);
	}

	if (_numCola == -1) {
		syslog(LOG_INFO,
				"Error al crear o obtener la Cola de Mensajes, ruta: %s, id: %c, crear: %i",
				ruta, id, crear);
		perror("Error al crear o obtener la Cola de Mensajes");
		perror(ruta);
		exit(EXIT_FAILURE);
	}
}

ColaMensajes::~ColaMensajes() {

}

#include "../defines.h"

void loguear(const void* msj) {
	MENSAJE* mensaje = (MENSAJE*) msj;

	syslog(LOG_INFO, "Error al tratar mensaje.Destino %li; Origen %li; id %i",
			mensaje->destinatario, mensaje->origen, mensaje->id);

}

bool ColaMensajes::recibir(void* msj, int tamMsj, int tipoEsperado,
		bool exitOnFailure) {

	long auxTipoEsp = (long) tipoEsperado;

	if (msgrcv(_numCola, msj, tamMsj, auxTipoEsp, 0) == -1) {
		char aux[2000];
		strncpy(aux, (const char*) msj, tamMsj);
		aux[tamMsj] = '\0';
		syslog(LOG_INFO,
				"Error al recibir Mensaje por Cola, msj: %s, tam: %i, tipoEsperado: %i",
				aux, tamMsj, tipoEsperado);

		loguear(msj);

		if (exitOnFailure) {
			perror("Error al recibir Mensaje por Cola");
			exit(EXIT_FAILURE);
		} else {
			return false;
		}
	}
	return true;
}

typedef struct{
	long int destinatario;
} structAux;

bool ColaMensajes::enviar(const void* msj, int tamMsj, bool exitOnFailure) {
	if (msgsnd(_numCola, msj, tamMsj, 0) == -1) {
		char aux[2000];
		strncpy(aux, (const char*) msj, tamMsj);
		aux[tamMsj] = '\0';
		syslog(LOG_INFO, "Error al enviar Mensaje por Cola, msj: %s, tam: %i",
				aux, tamMsj);
		loguear(msj);
		if (exitOnFailure) {
			structAux msjAux;
			memcpy(&msjAux,msj, sizeof(msjAux));
			sprintf(aux,
					"Error al enviar Mensaje por cola, errno: %s, destinatario: %li\n",
					strerror(errno), msjAux.destinatario);
			write(fileno(stdout), aux, strlen(aux));
			mostrarMensajeCompleto((MENSAJE*) msj);
			exit(EXIT_FAILURE);
		} else {
			return false;
		}
	}
	return true;
}

void ColaMensajes::crear() {
	// nada
}

void ColaMensajes::destruir() {

	if (msgctl(_numCola, IPC_RMID, NULL) == -1) {
		syslog(LOG_INFO, "Error al destruir la Cola");
		perror("Error al destruir la Cola");
//		exit(EXIT_FAILURE);
	}
}

void ColaMensajes::destruirCola(const char* ruta, char id) {
	key_t clave = ftok(ruta, id);

	if (clave == -1) {
		syslog(LOG_INFO, "Error al obtener clave [ftok(...)], ruta: %s, id: %c",
				ruta, id);
		perror("Error al obtener clave [ftok(...)]");
		return;
	}

	int numCola = msgget(clave, 0660);

	if (numCola == -1) {
		syslog(LOG_INFO,
				"Error al crear o obtener la Cola de Mensajes, ruta: %s, id: %c",
				ruta, id);
		perror("Error al crear o obtener la Cola de Mensajes");
		return;
	}

	if (msgctl(numCola, IPC_RMID, NULL) == -1) {
		syslog(LOG_INFO, "Error al destruir la Cola, ruta: %s, id: %c", ruta,
				id);
		perror("Error al destruir la Cola");
	}
}
